/** 
 * SimpleCharSequence.java
 * @author Lex
 * 2007-9-2 ����07:23:57
 */
package org.lex.utils.text;

import java.util.Arrays;

/**
 * ���ɱ��<code>CharSequence</code><br>
 * ����<code>subSequence(int,int)</code>����ʱ����ʹ�ù��?��ʡ�ռ俪��<br>
 * <br>
 * ע�⣺��Ϊ<code>char[] data<code>�ڶ���֮�乲�?���ܻ�������������һ���ܴ������
 * ֻ��һС���ֱ�ʹ�ã�����󲿷����ã��Ӷ���ɴ洢�ռ���˷�.
 */
public class ImmutableCharSequence implements CharSequence, Cloneable {
	private static final char[] EMPTY = new char[0];
	private char[] data = null;
	private int offset = 0;
	private int count = 0;

	/**
	 * ����ʱ��Բ���<code>data</code>���п�������֤�˶����ǲ��ɱ��
	 * 
	 * @param value
	 * @param offset
	 * @param length
	 */
	public ImmutableCharSequence(char[] value, int offset, int length) {
		if (offset < 0)
			throw new IndexOutOfBoundsException("Index out of range: " + offset);
		if (length < 0)
			throw new IndexOutOfBoundsException("Index out of range: " + length);
		if (length > value.length - offset)
			throw new IndexOutOfBoundsException("Index out of range: " + (offset + length));
		if (0 == value.length)
			this.data = EMPTY;
		else {
			this.data = Arrays.copyOfRange(value, offset, offset + length);
			this.offset = 0;
			this.count = length;
		}
	}

	public ImmutableCharSequence(char[] value) {
		this(value, 0, value.length);
	}

	public ImmutableCharSequence(CharSequence csq) {
		this.data = new char[csq.length()];
		for (int i = 0; i < data.length; i++)
			data[i] = csq.charAt(i);
		this.offset = 0;
		this.count = data.length;
	}

	public ImmutableCharSequence(ImmutableCharSequence src, int offset, int length) {
		if (null == src)
			throw new NullPointerException();
		// check range
		int len = src.length();
		if (offset < 0 || offset >= len)
			throw new IndexOutOfBoundsException("Index out of range: " + offset);
		if (length < 0 || length > len - offset)
			throw new IndexOutOfBoundsException("Index out of range: " + length);
		// ===================
		this.data = src.data;
		this.offset = src.offset + offset;
		this.count = length;
	}

	public char charAt(int index) {
		if (index >= count)
			throw new IndexOutOfBoundsException("Index out of range: " + index);
		return data[offset + index];
	}

	public int length() {
		return count;
	}

	public ImmutableCharSequence subSequence(int start, int end) {
		return new ImmutableCharSequence(this, start, end - start);
	}

	@Override
	public Object clone() {
		return this;
	}

	@Override
	public String toString() {
		return new String(data, offset, count);
	}
}
